package de.nabble.events;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.ResourceBundle;
import java.util.Set;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import de.nabble.Nabble;
import de.nabble.gui.BoardPanel;
import de.nabble.gui.RowPanel;
import de.nabble.model.Field;
import de.nabble.model.GameBoard;
import de.nabble.model.Letter;
import de.nabble.model.LetterRow;
import de.nabble.util.Helper;

public class EventHandler {
	
	private GameBoard board;
	private Letter letterToPut;
	private Letter takenLetter;
	private LetterRow row;
	private BoardPanel boardPanel;
	private RowPanel rowPanel;
	
	private Set<String> validWords;
	private List<Letter> lastLetters;
	
	private int deleteIndex;
	
	private ResourceBundle bundle = ResourceBundle
										.getBundle(Nabble.RESOURCE_PATH);
	
	public EventHandler(GameBoard board, LetterRow row) {
		this.board = board;
		this.row = row;
		validWords = loadWordFile(Nabble.WORD_FILE);
		lastLetters = new ArrayList<Letter>(7);
	}
	
	/**
	 * Checks the board if the words are valid.
	 */
	public boolean check() {
		List<String> wordsToCheck = getAllWords();
		boolean ok = true;
		
		Nabble.log(wordsToCheck);
		
		for(String s : wordsToCheck) {
			if(!validWords.contains(s)) {
				ok = false;
			}
		}
		
		if(ok) {
			lastLetters.clear();
			row.fill();
		} else {
			JOptionPane.showConfirmDialog(null, bundle.getString("Error.wrongWord.msg"), 
					bundle.getString("Error.wrongWord.title"), 
					JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE);
			for(Letter l : lastLetters) {
				row.putOne(l);
				for(Field[] fa : board.getFields()) {
					for(Field f : fa) {
						if(f.getLetter() != null) {
							if(f.getLetter().equals(l)) {
								f.setLetter(null);
							}
						}
					}
				}
			}
		}

		rowPanel.repaint();
		boardPanel.repaint();
		
		return ok;
	}
	
	/**
	 * Reads in all words on the board. Including invalid words!
	 */
	private List<String> getAllWords() {
		List<String> wordsToCheck = new ArrayList<String>();
		String tmpH = "";
		String tmpV = "";
		Field[][] field = board.getFields();
		
		for(int i = 0; i < field.length; i++) {
			for(int j = 0; j < field.length; j++) {
				
				if(field[j][i].getLetter() != null) {
					tmpH += field[j][i].getLetter().getValue();
				} else {
					tmpH += ",";
				}
				
				if(field[i][j].getLetter() != null) {
					tmpV += field[i][j].getLetter().getValue();
				} else {
					tmpV += ",";
				}
				
//				if(field[i][j].getLetter() != null && board.isLetterAlone(i, j)) {
//					tmpV += field[i][j].getLetter().getValue();
//				} else {
//					tmpV += ",";
//				}
			}
		}
		
		String[] all = Helper.<String>concatArrays(String.class, 
									tmpV.split(","), tmpH.split(","));
		
		for(String s : all) {
			if(s.length() >= 2) {
				wordsToCheck.add(s);
			}
		}
				
		return wordsToCheck;
	}
	
	/**
	 * Called by click on the letterrow.
	 * @param x the index of the letter in row
	 */
	public void clickOnRow(int x) {
		takenLetter = row.getLetters()[x];
		deleteIndex = x;
		
		deselectAll();
		
		if(takenLetter != null) {
			takenLetter.setSelected(true);	
		}
		
		letterToPut = takenLetter;
		rowPanel.repaint();
	}
	
	/**
	 * Called by click on board.
	 * @param x x coordinate
	 * @param y y coordinate
	 */
	public void clickOnBoard(int x, int y) {
		if(letterToPut != null) {
			board.setLetterOnField(letterToPut, x, y);
			letterToPut.setSelected(false);
			lastLetters.add(letterToPut);
			letterToPut = null;
			
			row.removeLetter(deleteIndex);
		}
		
		rowPanel.repaint();
		boardPanel.repaint();
	}
	
	public void connect(String url) {
		
	}
	
	public void disconnect() {
		
	}

	public void exit(int status) {
		System.exit(status);
	}
	
	public void showInfo(JFrame parent) {
		JOptionPane.showConfirmDialog(parent, bundle.getString("Info.message"), 
				bundle.getString("Info.title"), JOptionPane.PLAIN_MESSAGE, 
				JOptionPane.INFORMATION_MESSAGE);
	}

	public void restart() {
		
	}
	
	private void deselectAll() {
		for(Letter l : row.getLetters()) {
			if(l != null)
				l.setSelected(false);
		}
	}

	private Set<String> loadWordFile(String path) {
		HashSet<String> words = new HashSet<String>();
		try {
			BufferedReader br = new BufferedReader(new FileReader(path));
			String w = "";
			while((w = br.readLine()) != null) {
				words.add(w.toUpperCase());
			}
			
		} catch (FileNotFoundException e) {
			Nabble.log("wordfile not found!", e);
			exit(1);
		} catch (IOException e) {
			Nabble.log(e);
			exit(1);
		}
		
		return words;
	}
	
	public void setPanels(BoardPanel boardPanel, RowPanel rowPanel) {
		this.boardPanel = boardPanel;
		this.rowPanel = rowPanel;
	}
}
